package cn.iocoder.yudao.framework.business.basic.service;

import cn.iocoder.yudao.framework.business.basic.dao.mapper.CoreMapper;
import cn.iocoder.yudao.framework.business.basic.pojo.dto.QueryDTO;
import cn.iocoder.yudao.framework.business.basic.pojo.dto.SaveDTO;
import cn.iocoder.yudao.framework.business.basic.pojo.po.BaseEntity;
import cn.iocoder.yudao.framework.business.basic.pojo.po.MemberScopeEntity;
import cn.iocoder.yudao.framework.business.basic.pojo.vo.BaseVO;
import cn.iocoder.yudao.framework.common.exception.KnownServiceException;
import jakarta.annotation.Nullable;
import org.springframework.transaction.annotation.Transactional;

/**
 * <pre>
 * OOoO0OOoO0OOOooo0oOOOO0OOOOO0oooOO0ooOOO0Ooooo0OOOOo0ooooO0OOooo0Ooooo0OOOOO
 *  服务接口
 * OOoO0OOoO0OOOooo0oOOOO0OOOOO0oooOO0ooOOO0Ooooo0OOOOo0ooooO0OOooo0Ooooo0OOOOO
 * </pre>
 *
 * @author 山野羡民（1032694760@qq.com）
 * @since 2024/11/29
 */
@SuppressWarnings("unused")
public interface CrudService<ENTITY extends BaseEntity, VO extends BaseVO, SAVE extends SaveDTO, QUERY extends QueryDTO> extends ValidateService<ENTITY>, SimpleDetailService<VO>, ListService<VO, QUERY>, PageService<VO, QUERY>, CreateService<SAVE>, UpdateService<SAVE>, SaveService<SAVE>, SimpleDeleteService {

    CoreMapper<ENTITY> getInjectedMapper();

    ENTITY convertToEntity(SAVE param);

    @Transactional(rollbackFor = Exception.class)
    default Long create(SAVE param, @Nullable Long userId) {
        validateCanCreate(param, userId);
        ENTITY entity = convertToEntity(param);
        entity.setId(null);
        if (entity instanceof MemberScopeEntity aDo) {
            aDo.setUserId(userId);
        }
        beforeCreate(entity, userId);
        getInjectedMapper().insert(entity);
        afterCreate(entity);
        return entity.getId();
    }

    default void validateCanCreate(SAVE param, Long userId) throws KnownServiceException {

    }

    default void beforeCreate(ENTITY entity, @Nullable Long userId) {

    }

    default void afterCreate(ENTITY entity) {

    }

    @Transactional(rollbackFor = Exception.class)
    default boolean update(SAVE param, Long userId) {
        validateExists(param.getId(), userId);
        validateCanUpdate(param, userId);
        ENTITY updateObj = convertToEntity(param);
        updateObj.setId(param.getId());
        beforeUpdate(updateObj);
        boolean updated = getInjectedMapper().updateById(updateObj) > 0;
        afterUpdate(updateObj);
        return updated;
    }

    default void validateCanUpdate(SAVE param, Long userId) {

    }

    default void beforeUpdate(ENTITY entity) {

    }

    default void afterUpdate(ENTITY entity) {

    }

    @Transactional(rollbackFor = Exception.class)
    default boolean createOrUpdate(SAVE param, Long userId) {
        if (checkExists(param, userId)) {
            return update(param, userId);
        }
        return create(param, userId) > 0;
    }

    @Transactional(rollbackFor = Exception.class)
    default boolean delete(Long id, Long userId) {
        ENTITY entity = validateExists(id, userId);
        validateCanDelete(entity);
        beforeDelete(entity);
        boolean deleted = getInjectedMapper().deleteById(id) > 0;
        afterDelete(entity);
        return deleted;
    }

    default void validateCanDelete(ENTITY entity) {

    }

    default void beforeDelete(ENTITY entity) {

    }

    default void afterDelete(ENTITY entity) {

    }

}
